<?php

// Copyright 2019-2022 Hackware SpA <human@hackware.cl>
// This file is part of "Hackware Web Services Payment" and licensed under
// the terms of the GNU Affero General Public License version 3, or (at your
// option) a later version. You should have received a copy of this license
// along with the software. If not, see <https://www.gnu.org/licenses/>.

namespace Hawese\Payment\Gateways;

use Buzz\Client\FileGetContents as HttpClient;
use Nyholm\Psr7\Factory\Psr17Factory as Psr17ResponseFactory;
use Psr\Http\Message\ResponseInterface;

abstract class AbstractGateway
{
    protected $psr17Factory;
    protected $httpClient;

    public function __construct()
    {
        $this->psr17Factory = new Psr17ResponseFactory();
        $this->httpClient = new HttpClient($this->psr17Factory);
    }

    public function request(
        string $method,
        string $uri,
        $bodyParams = null,
        array $headers = []
    ): ResponseInterface {
        $builderName = static::requestBuilderName();
        $requestBuilder = new $builderName(
            $method,
            $uri,
            $bodyParams,
            $headers
        );

        return $this->httpClient->sendRequest($requestBuilder->build());
    }

    protected static function requestBuilderName(): string
    {
        return static::name() . 'RequestBuilder';
    }

    protected static function name(): string
    {
        return substr(static::class, 0, -7);
    }

    public static function schema(string $schema, array $defaults = []): array
    {
        $name = strtolower(
            substr(static::name(), strrpos(static::name(), '\\') + 1)
        );

        $schema = array_merge([
            '$schema' => 'http://json-schema.org/schema#',
            '$id' => route('gateways.schema', [
                'gateway' => $name,
                'schema' => $schema,
            ]),
            'type' => 'object',
        ], config("gateways.$name.schemas.$schema"));

        foreach ($schema['standard_map'] as $prop_input => $prop_schema) {
            $property = &static::schemaProperty(
                $schema,
                $prop_schema
            );
            if (array_key_exists($prop_input, $defaults)) {
                $property['default'] = static::schemaTypeCast(
                    $property['type'],
                    $defaults[$prop_input]
                );
                if ($prop_input == 'email') {
                    $property['readOnly'] = true;
                }
            }
        }
        return $schema;
    }

    protected static function schemaTypeCast(string $type, $value)
    {
        switch ($type) {
            case 'number':
            case 'integer':
                return $value * 1;
                break;
            default:
                return $value;
        }
    }

    protected static function &schemaProperty(array &$schema, $property)
    {
        if (is_array($property)) {
            $key = array_key_first($property);
            return static::schemaProperty(
                $schema['properties'][$key],
                $property[$key]
            );
        }
        return $schema['properties'][$property];
    }
}
